use axum::{
    extract::{Path, Query, State},
    http::StatusCode,
    response::Json,
};
use serde::{Deserialize, Serialize};

use crate::error::AppError;
use crate::models::User;
use crate::utils::AuthenticatedUser;

#[derive(Debug, Deserialize)]
pub struct ListUsersQuery {
    pub page: Option<i64>,
    pub page_size: Option<i64>,
    pub search: Option<String>,
}

#[derive(Debug, Serialize)]
pub struct PaginatedUsersResponse {
    pub users: Vec<User>,
    pub total: i64,
    pub page: i64,
    pub page_size: i64,
}

#[derive(Debug, Deserialize)]
pub struct PasswordReset {
    pub new_password: String,
}

#[derive(Debug, Serialize)]
pub struct GarbageCollectResult {
    pub files_removed: i64,
    pub space_freed: i64,
}

#[derive(Debug, Serialize)]
pub struct PublicDataItem {
    pub id: i64,
    pub name: String,
    pub description: Option<String>,
    pub project: Option<String>,
    pub source: String,
    pub file_size: Option<i64>,
    pub user_id: i64,
    pub user_email: String,
    pub is_public: bool,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub updated_at: chrono::DateTime<chrono::Utc>,
    pub lineage_count: i64,
    pub age_days: i64,
    pub safety_score: f64,
}

#[derive(Debug, Serialize)]
pub struct DataAnalysis {
    pub total_public_data: i64,
    pub total_storage_mb: f64,
    pub orphaned_count: i64,
    pub duplicate_count: i64,
    pub old_unused_count: i64,
    pub safe_to_delete_count: i64,
}

pub async fn list_users(
    AuthenticatedUser(current_user): AuthenticatedUser,
    Query(params): Query<ListUsersQuery>,
    State(state): State<crate::AppState>,
) -> Result<Json<PaginatedUsersResponse>, AppError> {
    // Check admin access
    let db_user = state
        .auth_service
        .get_user_by_email(&current_user.email)
        .await?;
    if !db_user.is_admin_bool() {
        return Err(AppError::Forbidden("Admin access required".to_string()));
    }

    let page = params.page.unwrap_or(1);
    let page_size = params.page_size.unwrap_or(20);
    let _search = params.search.as_deref();

    let (users, total) = state
        .auth_service
        .list_users(page, page_size, params.search)
        .await?;

    Ok(Json(PaginatedUsersResponse {
        users,
        total,
        page,
        page_size,
    }))
}

pub async fn get_user(
    Path(user_id): Path<i64>,
    AuthenticatedUser(current_user): AuthenticatedUser,
    State(state): State<crate::AppState>,
) -> Result<Json<User>, AppError> {
    // Check if user is admin or requesting their own info
    let db_user = state
        .auth_service
        .get_user_by_email(&current_user.email)
        .await?;
    if !db_user.is_admin_bool() && db_user.id != user_id {
        return Err(AppError::Forbidden("Access denied".to_string()));
    }

    let user = state.auth_service.get_user_by_id(user_id).await?;
    Ok(Json(user))
}

pub async fn toggle_admin_status(
    Path(user_id): Path<i64>,
    AuthenticatedUser(current_user): AuthenticatedUser,
    State(state): State<crate::AppState>,
) -> Result<Json<User>, AppError> {
    // Check admin access
    let db_user = state
        .auth_service
        .get_user_by_email(&current_user.email)
        .await?;
    if !db_user.is_admin_bool() {
        return Err(AppError::Forbidden("Admin access required".to_string()));
    }

    // Prevent admin from removing their own admin status
    if db_user.id == user_id {
        return Err(AppError::BadRequest(
            "Cannot modify your own admin status".to_string(),
        ));
    }

    let updated_user = state.auth_service.toggle_admin_status(user_id).await?;
    Ok(Json(updated_user))
}

pub async fn delete_user(
    Path(user_id): Path<i64>,
    AuthenticatedUser(current_user): AuthenticatedUser,
    State(state): State<crate::AppState>,
) -> Result<StatusCode, AppError> {
    // Check admin access
    let db_user = state
        .auth_service
        .get_user_by_email(&current_user.email)
        .await?;
    if !db_user.is_admin_bool() {
        return Err(AppError::Forbidden("Admin access required".to_string()));
    }

    // Prevent admin from deleting themselves
    if db_user.id == user_id {
        return Err(AppError::BadRequest(
            "Cannot delete your own account".to_string(),
        ));
    }

    // Prevent admin from deleting themselves
    if current_user.id == user_id {
        return Err(AppError::BadRequest(
            "Cannot delete your own account".to_string(),
        ));
    }

    // Get user's data items to delete files
    let (user_data_items, _) = state
        .data_service
        .list_data_items(user_id, None, None)
        .await?;

    // Delete user's files from storage
    for item in user_data_items {
        let _ = state.storage_service.delete_file(&item.file_path).await;
    }

    // Delete user's data items from database
    let _deleted_items_count = state.data_service.delete_user_data_items(user_id).await?;

    // Delete user from database
    let deleted = state.auth_service.delete_user(user_id).await?;

    if deleted {
        Ok(StatusCode::NO_CONTENT)
    } else {
        Err(AppError::NotFound("User not found".to_string()))
    }
}

pub async fn reset_user_password(
    Path(user_id): Path<i64>,
    State(state): State<crate::AppState>,
    AuthenticatedUser(current_user): AuthenticatedUser,
    Json(payload): Json<PasswordReset>,
) -> Result<StatusCode, AppError> {
    // Check if user is admin or resetting their own password
    let db_user = state
        .auth_service
        .get_user_by_email(&current_user.email)
        .await?;
    if !db_user.is_admin_bool() && db_user.id != user_id {
        return Err(AppError::Forbidden("Access denied".to_string()));
    }

    state
        .auth_service
        .reset_password(user_id, &payload.new_password)
        .await?;

    Ok(StatusCode::NO_CONTENT)
}

pub async fn admin_delete_data_item(
    Path(id): Path<i64>,
    AuthenticatedUser(current_user): AuthenticatedUser,
    State(state): State<crate::AppState>,
) -> Result<StatusCode, AppError> {
    // Check admin access
    let db_user = state
        .auth_service
        .get_user_by_email(&current_user.email)
        .await?;
    if !db_user.is_admin_bool() {
        return Err(AppError::Forbidden("Admin access required".to_string()));
    }

    // Get item info before deletion (admin can delete any item)
    let item = state.data_service.get_data_item_admin(id).await?;

    // Delete from database
    let deleted = state.data_service.delete_data_item_admin(id).await?;

    if deleted {
        // Delete file from storage
        let _ = state.storage_service.delete_file(&item.file_path).await;
        Ok(StatusCode::NO_CONTENT)
    } else {
        Err(AppError::NotFound("Data item not found".to_string()))
    }
}

pub async fn garbage_collect(
    AuthenticatedUser(current_user): AuthenticatedUser,
    State(state): State<crate::AppState>,
) -> Result<Json<GarbageCollectResult>, AppError> {
    // Check if user is admin
    if !current_user.is_admin_bool() {
        return Err(AppError::Forbidden("Admin access required".to_string()));
    }

    // Get storage path from config or use default
    let storage_path = "./storage";

    // Clean up orphaned files
    let files_removed = state
        .data_service
        .cleanup_orphaned_files(storage_path)
        .await?;

    // Clean up empty files
    let empty_files_removed = state.storage_service.cleanup_empty_files().await?;

    let total_files_removed = files_removed + (empty_files_removed as i64);

    Ok(Json(GarbageCollectResult {
        files_removed: total_files_removed,
        space_freed: 0, // TODO: Calculate actual space freed
    }))
}

pub async fn list_public_data(
    AuthenticatedUser(current_user): AuthenticatedUser,
    State(state): State<crate::AppState>,
) -> Result<Json<Vec<PublicDataItem>>, AppError> {
    // Check admin access
    let db_user = state
        .auth_service
        .get_user_by_email(&current_user.email)
        .await?;
    if !db_user.is_admin_bool() {
        return Err(AppError::Forbidden("Admin access required".to_string()));
    }

    // Get all public data items with safety analysis
    let public_items = state
        .data_service
        .list_public_data_with_safety()
        .await
        .map_err(|e| AppError::Internal(format!("Failed to list public data: {}", e)))?;

    Ok(Json(public_items))
}

pub async fn analyze_data_safety(
    AuthenticatedUser(current_user): AuthenticatedUser,
    State(state): State<crate::AppState>,
) -> Result<Json<DataAnalysis>, AppError> {
    // Check admin access
    let db_user = state
        .auth_service
        .get_user_by_email(&current_user.email)
        .await?;
    if !db_user.is_admin_bool() {
        return Err(AppError::Forbidden("Admin access required".to_string()));
    }

    // Perform data analysis
    let analysis = state
        .data_service
        .analyze_data_safety()
        .await
        .map_err(|e| AppError::Internal(format!("Failed to analyze data: {}", e)))?;

    Ok(Json(analysis))
}

pub async fn bulk_delete_safe_data(
    AuthenticatedUser(current_user): AuthenticatedUser,
    State(state): State<crate::AppState>,
) -> Result<Json<GarbageCollectResult>, AppError> {
    // Check admin access
    let db_user = state
        .auth_service
        .get_user_by_email(&current_user.email)
        .await?;
    if !db_user.is_admin_bool() {
        return Err(AppError::Forbidden("Admin access required".to_string()));
    }

    // Delete safe data items
    let result = state
        .data_service
        .bulk_delete_safe_data()
        .await
        .map_err(|e| AppError::Internal(format!("Failed to bulk delete data: {}", e)))?;

    Ok(Json(result))
}
